#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/6/23 11:43
# @Author  : Chenmm
# @File    : course_method.py
# @Software: PyCharm

from sqlalchemy.orm import Session

from common.json_tools import response
from methods.user_method import get_user_by_username, get_user_by_uid
from models.course_schema import Courses, CourseDetail, CourseEdit, CourseCommentOut, CourseCommentModel
from models.models import Course, CourseComment, StudentCourse
from models.user_schema import UsernameRole
from common.log import logger
import traceback
from datetime import datetime
from fastapi import Request


def get_course_by_name(db: Session, name: str):
    """根据名称获取课程"""
    return db.query(Course).filter(Course.name == name, Course.status == False).first()


def create_course(db: Session, course: Courses, user: UsernameRole):
    """创建课程"""
    user_role = user.role
    if not user_role or user_role == "学生":
        return response(code=101004, message="只有老师才可以创建课程")
    db_course = get_course_by_name(db, course.name)
    if db_course:
        return response(code=101002, message="该课程名称已存在，不允许重复")
    try:
        db_user = get_user_by_username(db, user.username)
        course.owner = db_user.id
        course = Course(**course.model_dump())
        db.add(course)
        db.commit()
        db.refresh(course)
    except:
        logger.warning(f"创建课程：{course.name} 失败")
        return response(code=101001, message="创建课程失败")
    logger.info(f"创建课程：{course.name} 成功")
    return response()


def get_course_by_id(db: Session, id: int):
    """根据课程id获取课程"""
    return db.query(Course).filter(Course.id == id, Course.status == False).first()


def get_comment_by_course_id(db: Session, course_id: int):
    return db.query(CourseComment).filter(CourseComment.course == course_id, CourseComment.status == False).all()


def get_course_detail(course_id: int, db: Session):
    """获取课程详情"""
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=101101, message="该课程不存在")
    try:
        course_detail = CourseDetail(
            id=db_course.id,
            name=db_course.name,
            icon=db_course.icon,
            desc=db_course.desc,
            catalog=db_course.catalog,
            onsale=db_course.onsale,
            owner=get_user_by_uid(db, db_course.owner).username,
            like_num=db_course.like_num
        )
        course_comments = get_comment_by_course_id(db, db_course.id)
        to_client_comments = []
        if course_comments:
            for _ in course_comments:
                detail_comment = CourseComment(
                    id=_.id,
                    top=_.top,
                    user=get_user_by_uid(db, _.user).username,
                    pid=_.pid,
                    add_time=str(_.add_time),
                    context=_.context
                )
                to_client_comments.append(detail_comment)
        course_detail.comment = to_client_comments
    except:
        logger.warning(f"查看课程详情失败")
        return response(code=101102, message="查看详情失败")
    return response(data=course_detail.model_dump())


def edit_course(course: CourseEdit, db: Session, user: UsernameRole):
    """编辑课程"""
    db_course = get_course_by_id(db, course.id)
    if not db_course:
        return response(code=101201, message="课程不存在")
    db_user = get_user_by_username(db, user.username)
    print('db_user.id = ', db_user.id)
    print('course.owner = ', db_course.owner)
    if db_user.id != db_course.owner:
        return response(code=101202, message="权限不足")
    exists = get_course_by_name(db, course.name)
    if exists:
        return response(code=101203, message="该课程名称已存在")
    try:
        # 这里只是修改课程的属性，上架下架不能在这改
        db_course.catalog = course.catalog
        db_course.desc = course.desc
        db_course.icon = course.icon
        db_course.name = course.name
        db.commit()
        db.refresh(db_course)
    except:
        logger.warning(f"method edit_course error：{traceback.format_exc()}")
        return response(code=101204, message="修改失败")
    return response()


def get_course_comment(course_id: int, db: Session):
    """获取课程评论"""
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=101301, message="课程不存在")
    comments = get_comment_by_course_id(db, course_id)
    to_client = []
    if comments:
        for _ in comments:
            detail_comment = CourseCommentOut(
                id=_.id,
                top=_.top,
                user=get_user_by_uid(db, _.user).username,
                pid=_.pid,
                add_time=str(_.add_time),
                context=_.context
            )
            to_client.append(detail_comment.model_dump())
    return response(data=to_client)


def to_comment_method(comment: CourseCommentModel, user: UsernameRole, db: Session):
    """发起评论"""
    db_user = get_user_by_username(db, user.username)
    db_course = get_course_by_id(db, comment.id)
    if not db_course:
        return response(code=101401, message="课程不存在")
    if db_course.owner == db_user.id and comment.pid is None:
        return response(code=101404, message="自己不能评论自己的课程")
    if comment.pid:
        pid_course = get_comment_by_pid(db, comment.pid)
        if not pid_course:
            return response(code=101405, message="回复的评论不存在")
        return create_comment(db, comment, db_user.id)
    return create_comment(db, comment, db_user.id)


def get_comment_by_pid(db: Session, pid: int):
    return db.query(CourseComment).filter(CourseComment.id == pid, CourseComment.status == False).first()


def create_comment(db: Session, comment: CourseCommentModel, user: int):
    """保存评论"""
    # 前提：自己不能给自己的课程发起评论，但是发起评论后可以给自己的评论回复
    try:
        to_db_comment = CourseComment(
            course=comment.id,
            user=user,
            pid=comment.pid,
            context=comment.comment
        )
        to_db_comment.user = user
        db.add(to_db_comment)
        db.commit()
        db.refresh(to_db_comment)
    except:
        logger.warning(f"method create_comment error: {traceback.format_exc()}")
        return response(code=101402, message="评论失败")
    return response()


def get_student_course(db: Session, course: int, student: int):
    """查询学生名下某个课程"""
    return db.query(StudentCourse).filter(
        StudentCourse.course == course, StudentCourse.student == student,
        StudentCourse.status == False).first()


def add_student_course(course_id: int, user: UsernameRole, db: Session):
    """添加课程"""
    if user.role == "老师":
        return response(code=101503, message="老师不能加入课程")
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=101501, message="课程不存在")
    db_user = get_user_by_username(db, user.username)
    exists = get_student_course(db, db_course.id, db_user.id)
    if exists:
        return response(code=101502, message="课程不能重复加入")
    try:
        s_course = StudentCourse(
            student=db_user.id,
            course=db_course.id
        )
        db.add(s_course)
        db.commit()
        db.refresh(s_course)
    except:
        logger.warning(f"加入课程：{db_course.name} 失败")
        return response(code=101504, message="课程加入失败")
    return response()


def del_student_course(course_id: int, user: UsernameRole, db: Session):
    """退出课程"""
    if user.role == "老师":
        return response(code=101603, message="老师不能退出课程")
    db_user = get_user_by_username(db, user.username)
    db_student_course = get_student_course(db, course_id, db_user.id)
    if not db_student_course:
        return response(code=101602, message="课程不在自己课表内")
    try:
        db_student_course.status = True
        db_student_course.update_time = datetime.now()
        db.add(db_student_course)
        db.commit()
        db.refresh(db_student_course)
    except:
        logger.warning(f"退出课程：{course_id} 失败")
        return response(code=101601, message="退出课程失败")
    return response()


def get_all(db: Session):
    return db.query(Course).filter(Course.status == False).all()


def get_all_courses(db: Session):
    """查询所有课程列表"""
    try:
        all_courses = get_all(db)
        to_client = []
        if all_courses:
            for _ in all_courses:
                course_detail = CourseDetail(
                    id=_.id,
                    name=_.name,
                    icon=_.icon,
                    desc=_.desc,
                    catalog=_.catalog,
                    onsale=_.onsale,
                    owner=get_user_by_uid(db, _.owner).username,
                    like_num=_.like_num
                )
                ####
                comments = get_comment_by_course_id(db, _.id)
                to_client_comments = []
                if comments:
                    for __ in comments:
                        detail_comment = CourseCommentOut(
                            id=__.id,
                            top=__.top,
                            user=get_user_by_uid(db, __.user).username,
                            pid=__.pid,
                            add_time=str(__.add_time),
                            context=__.context
                        )
                        to_client_comments.append(detail_comment.model_dump())
                course_detail.comment = to_client_comments
                ####
                to_client.append(course_detail.model_dump())
    except:
        logger.warning(f"查询失败：{traceback.format_exc()}")
        return response(code=101701, message="查询失败")
    return response(data=to_client)


def db_student_like(db: Session, user_id: int):
    """学生加入的所有课程"""
    return db.query(StudentCourse).filter(StudentCourse.student == user_id, StudentCourse.status == False).all()


def get_student_like(user: UsernameRole, db: Session):
    """查询学生加入的所有课程"""
    if user.role == "老师":
        return response(code=101701, message="只有学生可以查看自己加入的课程列表")
    try:
        db_user = get_user_by_username(db, user.username)
        student_likes = db_student_like(db, db_user.id)
        to_client = []
        if student_likes:
            for _ in student_likes:
                db_course = get_course_by_id(db, _.course)
                course_detail = CourseDetail(
                    id=db_course.id,
                    name=db_course.name,
                    icon=db_course.icon,
                    desc=db_course.desc,
                    catalog=db_course.catalog,
                    onsale=db_course.onsale,
                    owner=get_user_by_uid(db, db_course.owner).username,
                    like_num=db_course.like_num
                )
                ####
                comments = get_comment_by_course_id(db, _.id)
                to_client_comments = []
                if comments:
                    for __ in comments:
                        detail_comment = CourseCommentOut(
                            id=__.id,
                            top=__.top,
                            user=get_user_by_uid(db, __.user).username,
                            pid=__.pid,
                            add_time=str(__.add_time),
                            context=__.context
                        )
                        to_client_comments.append(detail_comment.model_dump())
                course_detail.comment = to_client_comments
                ####
                to_client.append(course_detail.model_dump())
    except:
        logger.warning(f"method get_student_like error: {traceback.format_exc()}")
        return response(code=101702, message="查询失败")
    return response(data=to_client)


def get_like_course(db: Session):
    """获取推荐课程（点赞数超500的课程）"""
    return db.query(Course).filter(Course.like_num > 500, Course.status == False).all()


def like_method(db: Session):
    """返回推荐课程逻辑"""
    try:
        all_likes = get_like_course(db)
        to_client = []
        if all_likes:
            for _ in all_likes:
                course_detail = CourseDetail(
                    id=_.id,
                    name=_.name,
                    icon=_.icon,
                    desc=_.desc,
                    catalog=_.catalog,
                    onsale=_.onsale,
                    owner=get_user_by_uid(db, _.owner).username,
                    like_num=_.like_num
                )
                to_client.append(course_detail.model_dump())
    except:
        logger.warning(f"method like_method error: {traceback.format_exc()}")
        return response(code=101801, message="查询错误")
    return response(data=to_client)


async def add_like_method(request: Request, course_id: int, user: UsernameRole, db: Session):
    """点赞课程"""
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=102001, message="课程不存在")
    if user.role != "学生":
        return response(code=102004, message="只有学生才可以点赞")
    like_key = str(db_course.id) + "_like"
    redis_result = await request.app.state.redis.hgetall(like_key, encoding="utf-8")
    username = user.username
    if username in redis_result.keys():
        return response(code=102002, message="不能重复点赞")
    try:
        await request.app.state.redis.hmset_dict(like_key, {username: 1})
        db_course.like_num += 1
        db.commit()
        db.refresh(db_course)
    except:
        logger.warning(f"method add_like_method error: {traceback.format_exc()}")
        return response(code=102003, message="点赞失败")
    return response()


# 取消点赞
async def delete_like_method(request: Request, course_id: int, user: UsernameRole, db: Session):
    """点赞课程"""
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=102001, message="课程不存在")
    if user.role != "学生":
        return response(code=102004, message="只有学生才可以点赞")
    like_key = str(db_course.id) + "_like"
    redis_result = await request.app.state.redis.hgetall(like_key, encoding="utf-8")
    username = user.username
    if username not in redis_result.keys():
        return response(code=102002, message="还未点赞")

    try:
        await request.app.state.redis.hdel(like_key, username)
        db_course.like_num -= 1
        db.commit()
        db.refresh(db_course)
    except:
        logger.warning(f"method add_like_method error: {traceback.format_exc()}")
        return response(code=102003, message="取消点赞失败")
    return response()



def onsale_method(course_id: int, user: UsernameRole, db: Session):
    """上架/下架 课程"""
    if user.role == "学生":
        return response(code=102101, message="权限不足")
    db_course = get_course_by_id(db, course_id)
    if not db_course:
        return response(code=102102, message="课程不存在")
    db_user = get_user_by_username(db, user.username)
    if db_user.id != db_course.owner:
        return response(code=102103, message="自己只能上架或下架自己的课程")
    try:
        if db_course.onsale:  # 下架
            db_course.onsale = False
        else:  # 上架
            db_course.onsale = True
        db.commit()
        db.refresh(db_course)
    except:
        logger.warning(f"method onsale_method error: {traceback.format_exc()}")
        if db_course.onsale:
            msg = "下架失败"
        else:
            msg = "上架失败"
        return response(code=102104, message=msg)
    return response()